﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DirectShowLib;
using DirectShowLib.Sample;
// Add reference C:\Windows\Microsoft.NET\DirectX for Managed Code\1.0.2902.0\Microsoft.DirectX.Direct3D.dll
//using Microsoft.DirectX.Direct3D;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;
using PTCapture.Support;

namespace PTCapture.UserControls
{
    public partial class MoviePlayerUIControl : UserControl
    {
        #region Fields

        /// <summary>
        /// Brightness range
        /// </summary>
        public float brightnessMax, brightnessMin;

        /// <summary>
        /// Contrast range
        /// </summary>
        public float contrastMax, contrastMin;

        /// <summary>
        /// Timer for trackbar
        /// </summary>
        private Timer timer;

        /// <summary>
        /// Prevent checking trackbar if we are setting it.
        /// </summary>
        private bool checkTrackbar = true;

        #endregion

        #region Delegates

        /// <summary>
        /// Tie to parent form to assign images on snapshot
        /// </summary>
        /// <param name="videoPath"></param>
        /// <param name="imagePath"></param>
        /// <returns></returns>
        public delegate bool customHandler(string imageName);
        public event customHandler SnapshotTaken;

        #endregion

        #region Initialization

        /// <summary>
        /// Constructor
        /// </summary>
        public MoviePlayerUIControl()
        {
            InitializeComponent();

            trackBar1.ValueChanged += new EventHandler(trackBar1_ValueChanged);

            timer = new Timer();
            timer.Interval = 100;
            timer.Tick += new EventHandler(timer_Tick);
        }

        #endregion

        #region Controls

        /// <summary>
        /// Change movie position
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            if (checkTrackbar &&
                moviePlayerControl1.MediaPosition != null && 
                (moviePlayerControl1.CurrentState == PlayState.Running ||
                 moviePlayerControl1.CurrentState == PlayState.Paused))
            {
                double stopTime = 0;
                moviePlayerControl1.MediaPosition.get_StopTime(out stopTime);

                // Value is from 0-100
                double desiredPosition = (stopTime / 100f) * trackBar1.Value;
                moviePlayerControl1.MediaPosition.put_CurrentPosition(desiredPosition);

                TimeSpan time = TimeSpan.FromSeconds(desiredPosition);
                lblCurrent.Text = string.Format("{0}m {1}.{2}s", time.Minutes, time.Seconds, time.Milliseconds);
            }
        }

        /// <summary>
        /// Change trackbar position and labels
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void timer_Tick(object sender, EventArgs e)
        {
            checkTrackbar = false;

            UpdatePositionData(false);

            checkTrackbar = true;
        }

        /// <summary>
        /// Change brightness
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tbBrightness_Scroll(object sender, EventArgs e)
        {
            // Trackbars are constrained from 0..100, so just convert to value from percent
            float value = brightnessMin + ((brightnessMax - brightnessMin) * (tbBrightness.Value / 100f));

            moviePlayerControl1.SetValue(VMR9ProcAmpControlFlags.Brightness, value);
        }

        /// <summary>
        /// Change contrast
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void tbContrast_Scroll(object sender, EventArgs e)
        {
            // Trackbars are constrained from 0..100, so just convert to value from percent
            float value = contrastMin + ((contrastMax - contrastMin) * (tbContrast.Value / 100f));

            moviePlayerControl1.SetValue(VMR9ProcAmpControlFlags.Contrast, (float)tbContrast.Value);
        }

        /// <summary>
        /// Take a snapshot and save it
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnSnapshot_Click(object sender, EventArgs e)
        {
            int hr = 0;

            double currentPosition;
            hr = moviePlayerControl1.MediaPosition.get_CurrentPosition(out currentPosition);
            DsError.ThrowExceptionForHR(hr);
            TimeSpan ts = new TimeSpan(0, 0, 0, 0, (int)(currentPosition * 1000));

            int bufferSize = 0;
            IntPtr buffer = new IntPtr();

            hr = moviePlayerControl1.BasicVideo.GetCurrentImage(ref bufferSize, IntPtr.Zero);
            DsError.ThrowExceptionForHR(hr);

            buffer = Marshal.AllocHGlobal(bufferSize);
            hr = moviePlayerControl1.BasicVideo.GetCurrentImage(ref bufferSize, buffer);
            DsError.ThrowExceptionForHR(hr);

            BitmapInfoHeader bitmapHeader = (BitmapInfoHeader)Marshal.PtrToStructure(buffer, typeof(BitmapInfoHeader));
            Bitmap bmp = new Bitmap(bitmapHeader.Width,
                                bitmapHeader.Height,
                                (bitmapHeader.BitCount / 8) * bitmapHeader.Width,
                                PixelFormat.Format32bppRgb,
                                buffer);
            bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);

            string[] filenameBreakdown = moviePlayerControl1.FileName.Split('\\');
            string filename = filenameBreakdown[filenameBreakdown.Length - 1];
            filename = string.Format("{0}\\Taken_{1}_FromVideo_{2}_AtTime_{3}.png", GlobalVariables.ImagePath, TimeFunctions.CurrentTimeStamp(), filename.Substring(0, filename.Length - 4), TimeFunctions.ConvertMinute(ts));
            bmp.Save(filename);

            Marshal.FreeHGlobal(buffer);

            // Call back to the parent to reassign images;
            SnapshotTaken(filename);
        }

        #endregion

        #region Support

        /// <summary>
        /// Close player interfaces and release.
        /// </summary>
        public void CloseInterfaces()
        {
            moviePlayerControl1.CloseInterfaces();
        }

        public void StartTimer()
        {
            timer.Start();
        }

        /// <summary>
        /// Update labels and trackbar.
        /// </summary>
        /// <param name="forceCheck">Force an update. Because we're paused during steps forwards and backwards, can't just check the running state.</param>
        public void UpdatePositionData(bool forceCheck)
        {
            checkTrackbar = false;

            if (moviePlayerControl1.MediaPosition != null &&
                (moviePlayerControl1.CurrentState == PlayState.Running ||
                    forceCheck))
            {
                // Set labels
                double stopTime = 0;
                moviePlayerControl1.MediaPosition.get_StopTime(out stopTime);

                double currentPosition = 0;
                moviePlayerControl1.MediaPosition.get_CurrentPosition(out currentPosition);

                TimeSpan time = TimeSpan.FromSeconds(stopTime);
                lblEnd.Text = string.Format("{0}m {1}.{2}s", time.Minutes, time.Seconds, time.Milliseconds);

                time = TimeSpan.FromSeconds(currentPosition);
                lblCurrent.Text = string.Format("{0}m {1}.{2}s", time.Minutes, time.Seconds, time.Milliseconds);

                // Set trackbar
                trackBar1.Value = (int)((currentPosition / stopTime) * 100);
            }

            checkTrackbar = true;
        }

        #endregion
    }
}
